#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/select.h>


int my_recv(int sockfd,char* buf,int length){

    int temp=0;
    int ftemp=0;

    while(1){
        
        ftemp=recv(sockfd,buf+temp,length - temp,0);//0 阻塞(发送的缓冲区满/网络阻塞);
        if(ftemp == -1){
            perror("my_send err");
            return -1;
        }if(ftemp == 0){
            return 0;
        }
        temp+=ftemp;
        if(temp >= length){
            break;
        }
        
    }
    return temp;
}


int main(void){
    int sockfd = socket(AF_INET,SOCK_STREAM,0);//ipv4,tcp
    if(sockfd == -1){
        perror("sock err");
        return -1;
    }
    //服务器地址:IP 端口号
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port =htons(8888);
    
    addr.sin_addr.s_addr=INADDR_ANY;//本地的ip都可以
    printf("IP=%s\n",inet_ntoa(addr.sin_addr));
    socklen_t addrlen= sizeof(addr);
    //绑定
    if(bind(sockfd,(struct sockaddr*)&addr,addrlen) == -1){
        perror("bind err");
        close(sockfd);
        return -1;
    }

    //监听
    if(listen(sockfd,5) == -1){
        perror("listen err");
        close(sockfd);
        return -1;
    }
    printf("waiting client connect!\n");
    int maxfd=sockfd;
    //响应连接
    struct sockaddr_in client_addr;
    socklen_t clientlen;
    int clientfd=-1;

    fd_set rdfds;//创建空表
    fd_set fd_cpy;//创建空表
    FD_ZERO(&rdfds);//清处表
    FD_ZERO(&fd_cpy);//清处表
    FD_SET(sockfd,&rdfds);


    char buf[64]="";

    while(1){
        FD_ZERO(&fd_cpy);//清处表
        memcpy(&fd_cpy,&rdfds,sizeof(rdfds));//复制描述符表
        int ret = select(maxfd+1,&fd_cpy,NULL,NULL,NULL);
        if(ret < 0){
            perror("select err");
            continue;
        }else if(ret > 0){
            if(FD_ISSET(sockfd,&rdfds)){
                clientfd=accept(sockfd,(struct sockaddr*)&client_addr,&clientlen);
                if(clientfd < 0){
                    perror("accept err");
                    continue;
                }
                printf("new connect comming\n");
                FD_SET(clientfd,&rdfds);
                if(clientfd > maxfd){
                    maxfd=clientfd;
                }
            }

            for(int fd=0;fd<=maxfd;fd++){
                if(FD_ISSET(fd,&rdfds) && fd != sockfd){
                    ret = recv(clientfd, buf,64, 0);
                    if (ret < 0){
                        perror("recv err");
                        close(fd);
                        FD_CLR(fd, &rdfds);
                        continue;
                    }
                    else if (ret == 0){
                        printf("peer exit\n");
                        close(fd);
                        FD_CLR(fd, &rdfds);
                        continue;
                    }
                    else{
                        buf[63]='\0';
                        printf("clientfd = %d\n",fd);
                        printf("data:%s\n",buf);
                    }
                }
            }
            
        }else{
            printf("超时\n");
        }
    }

    //关闭
    close(clientfd);
    close(sockfd);


    return 0;
}
